home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / doc.lha / documentation / manual / foreign.mss < prev    next >
Text File  |  1987-06-30  |  6KB  |  143 lines

  1. @Part(ForeignCode, Root "TMAN.MSS")
  2. @Chap(Foreign Code)
  3.  
  4. @section[Foreign Objects]
  5.  
  6. @i[Xenoids] are used to hold single machine pointers
  7. which @tau[] needs to use,  but which are not
  8. @tau[] objects.  Two examples are:  the file
  9. descriptor that the operating system returns when a file is opened; and,
  10. the address of a system or non-@tau[] routine.
  11.  
  12. @i[Bit vectors] can be used to hold foreign objects larger than a
  13. single machine pointer. [Bit vectors are not yet implemented].
  14.  
  15. @section[Calling Foreign Code in  VAX @tau[]]
  16. The form of interest here is @tc[CALL-XENOID].
  17.  
  18. @section[Calling Foreign Code in Apollo @tau[]]
  19. @desc[(EXTERNAL-SYMBOL-ADDRESS @i[string])]
  20. This routine returns a non-@tau[] pointer that is the machine address
  21. of the process global routine whose name is @i[string].  To get a xenoid,
  22. @tc[X], that can be passed to @tc[CALL-XENOID] to do program invocation,
  23. one might say:
  24. @begin[ProgramExample]
  25. (SET X (MAKE-XENOID (EXTERNAL-SYMBOL-ADDRESS "pgm_$invoke")))
  26. @end[ProgramExample]
  27. @EndDesc[EXTERNAL-SYMBOL-ADDRESS]
  28.  
  29. @desc[(CALL-XENOID @i[ret-info-1 ret-info-2 callable-xenoid . argument-items])]
  30. Call the foreign code pointed to by the @i[callable-xenoid] using
  31. the Apollo calling sequence.  The @i[callable-xenoid] is create as described
  32. above.
  33.  
  34. Since the Apollo calling sequence is call by reference, and @tau[]'s is call
  35. by value,  extra space is need on the stack for pointers (the @qu"references"),
  36. to the values that were intended as arguments to the Apollo code being called.
  37. The lowest level call to invoke Apollo code (i.e. code
  38. that uses the Apollo calling sequence)  is designed so that the stack
  39. pointer need not be adjusted before making the foreign call.
  40. This is done by requiring extra arguments to @tc[CALL-XENOID].
  41.  
  42. In addition to providing room on the stack,  the extra arguments also
  43. indicate conversions that should be performed on the @tau[] values
  44. that are on the stack, to make them suitable for the foreign code to
  45. use.  To complicate things further,  the Apollo and @tau[] calling
  46. sequences require arguments in the opposite order.
  47.  
  48. Argument items can be: a single character that
  49. holds a place for a @qu"reference" and may indicate a data conversion,
  50. a @tau[] value.  In preparing for the call to foreign code
  51. some values are not touched,  some are converted to a format
  52. suitable for the foreign code, and some are converted according to one of the
  53. argument specs.
  54.  
  55. There are two kinds of argument items -- value items, and reference
  56. items.  The value items occur before the reference items.  For every
  57. value item there is a corresponding reference item, but there may be
  58. reference items with no value items.  For each parameter to the foreign
  59. code there is one reference item.  The last reference item in the
  60. @tc[CALL-XENOID] form refers to the first foreign code parameter; the
  61. first reference item to the last foreign code parameter.  If a reference
  62. item @qu"needs" a value item, it uses (gets? matches?) the next unused
  63. one, starting from the first (leftmost) value item in the form.
  64.  
  65. If you want to pass a string just put the @tau[] string in the appropriate
  66. position in the reference items.  If you want to pass the length of
  67. that string, put a lower case character @qu"s," @tc[#\s],
  68. in the appropriate position in the reference items. Notice
  69. that @tc[#\s] gives a reference to a word long integer that is the
  70. actual length field of the last string encountered in the
  71. reference items, starting from the rightmost one.
  72. To pass a 32 bit integer, put @tc[#\l] in the reference items and
  73. put the integer in corresponding position in the value items; use
  74. @tc[#\w] for a 16 bit integer.
  75.  
  76. Arbitrary extends can be passed by putting them in the reference
  77. items at the appropriate place.  Bit vectors are arbitrary
  78. extends, as are xenoids.
  79.  
  80. For example, suppose we want to call a PASCAL procedure, @tc[x_$test],
  81. that expects
  82. a string (packed array of char), it length as a word long integer,
  83. a 16 bit integer, a 32 bit integer, and a status code.
  84. Assume @tc[I] is the @tau[] fixnum that we want to pass of the word
  85. parameter, @tc[J] will be passed as the longword.
  86. We might write:
  87. @begin[ProgramExample]
  88. (SET X_$TEST (MAKE-XENOID (EXTERNAL-SYMBOL-ADDRESS "x_$test")))
  89. (SET STATUS (MAKE-XENOID 0))
  90. (CALL-XENOID 'VOID NIL X_$TEST  I J  STATUS #\l #\w  #\s "My string")
  91. @end[ProgramExample]
  92.  
  93. @tc[XENOID-POINTER] is a procedure that returns the 32 bit field of a
  94. given xenoid.  Be careful,  it returns an unsafe value.
  95.  
  96. The manner in which the value is returned from the foreign code is controlled
  97. by the two arguments @i[ret-info-1] and @i[ret-info-2].  The Apollo
  98. calling sequence allows three variations on the value returned:
  99. @begin[display]
  100.     return no value
  101.     return an @qu(address)
  102.     return up to 32 bits of data
  103. @end[display]
  104. If the foreign code does indeed return a value, @tau[] can:
  105. @begin[display]
  106.     convert value to a fixnum  (multiply by 8)
  107.     convert value to a pointer (a no-op actually)
  108.     store value in a xenoid as a fixnum
  109.     store value in a xenoid as a pointer
  110. @end[display]
  111. Of the 12 possibilities, 7 are legal and are encoded in the two info
  112. arguments.  Roughly speaking, @i[ret-info-1] describes the form
  113. of the return value from the Apollo side, and @i[ret-info-2] describes
  114. the value from the @tau[] side.
  115. @begin[display]
  116. @tabdivide(6)
  117. @i[ret-info-1]@\@i[ret-info-2]@\action
  118.  
  119. @tc['ADDR] @\@tc['POINTER] @\Return returned address as a @tau[] pointer.
  120. @tc['ADDR] @\@tc['FIXNUM]  @\Return returned address as a @tau[] fixnum.
  121. @tc['ADDR] @\@i[xenoid]   @\Store returned address into the given @i[xenoid].
  122.           @\             @\(Return @i[xenoid])
  123.  
  124. @tc['DATA] @\@tc['POINTER] @\Return 32 bits of returned data as a @tau[] pointer.
  125. @tc['DATA] @\@tc['FIXNUM]  @\Return 29 bits of returned data as a @tau[] fixnum.
  126. @tc['DATA] @\@i[xenoid]   @\Store 32 bits of data into the given @i[xenoid].
  127.           @\             @\(Return @i[xenoid])
  128.  
  129. @tc['VOID]@\@i[anything]  @\Ignore foreign code's return value (if any).
  130.           @\             @\(Return @i[anything])
  131. @end[display]
  132.  
  133. Yet to be discussed:
  134. @begin[itemize]
  135. OUT parameters that are integers (long or word) are a pain in the
  136. neck - you must use a xenoid to box the data yourself
  137.  
  138. it is safest (essential?) to gc-defer while doing call-xenoid
  139.  
  140. The higher level interface -- coping with PASCAL records
  141. @end[itemize]
  142. @EndDesc[CALL-XENOID]
  143.